package com.dcivision.framework;

import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Hashtable;

import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.dcivision.framework.bean.LicenceInfo;
import com.dcivision.framework.bean.ModuleLicenceInfo;
import com.dcivision.framework.xml.XMLUtility;

public class SiteValidator {

  public static final String REVISION = "$Revision: 1.17.24.1 $";

  protected static Category log = Category.getInstance("com.dcivision.framework.SiteValidator");

  private static Object lock = new Object();

  static Document document;
  private Hashtable Modules;
  private LicenceInfo Info;
  private XMLUtility XMLfile;
  private String path;
  private MD5Utility md5util;

  private boolean readFlag = false;
  private boolean isValidLicense = false;
  
  //EIP-2211
  private InputStream xmlInput;

  public SiteValidator(String filePath) {
    path = filePath;
  }
  
  /**
   * EIP-2211
   * to be used when the content is being made available from a .war archive
   * @param xmlInputStream
   */
  public SiteValidator(InputStream xmlInputStream) {
    xmlInput = xmlInputStream;
  }

  public int getModuleUser(String name) {
    ModuleLicenceInfo ml = (ModuleLicenceInfo) Modules.get(name);
    if (ml != null)
      return ml.getNo();
    else
      return -1;
  }

  public String getModuleLicenceInfoType(String name) {
    ModuleLicenceInfo ml = (ModuleLicenceInfo) Modules.get(name);
    if (ml != null)
      return ml.getType();
    else
      return "N/A";
  }

  public String getExpDate() {
    return Info.getExpDate();
  }

  private void getXMLElements() {
    synchronized(lock) {
      if (this.readFlag) {
        return;
      }
  
      document = null;
      Modules = new Hashtable();
      Info = new LicenceInfo();
      log.info("License File Path: " + path);
 
      /* EIP-2211
       * to fix getRealPath method null error
       * when the content is being made available from a .war archive
       */
      if (path != null) {
        XMLfile = new XMLUtility(path);
      } else {
        XMLfile = new XMLUtility(xmlInput);
        if(XMLfile!=null){
          log.debug("XMLUtility build with xmlInputStream success");
        }
      }
  
      try {
        NodeList rootlist = XMLfile.getNodeListByTagName("MODULE");
        for (int intloop = 0; intloop < rootlist.getLength(); intloop++) {
          ModuleLicenceInfo ml = new ModuleLicenceInfo();
          Element node = (Element)rootlist.item(intloop);
  
          ml.setName(node.getElementsByTagName("MODULE_CODE").item(0).getChildNodes().item(0).getNodeValue());
          if (node.getElementsByTagName("CONCURRENT_USER") != null && node.getElementsByTagName("CONCURRENT_USER").getLength() > 0) {
            ml.setType("CONCURRENT_USER");
            ml.setNo(Integer.parseInt(node.getElementsByTagName("CONCURRENT_USER").item(0).getChildNodes().item(0).getNodeValue()));
          } else {
            ml.setType("NAMED_USER");
            ml.setNo(Integer.parseInt(node.getElementsByTagName("NAMED_USER").item(0).getChildNodes().item(0).getNodeValue()));
          }
          log.info(ml.getName() + ":" + ml.getType() + ":" + ml.getNo());
          Modules.put(ml.getName(), ml);
        }
  
        Element infoNode = (Element)XMLfile.getNodeListByTagName("INFORMATION").item(0);
        Info = new LicenceInfo();
        Info.setKey(infoNode.getElementsByTagName("LICENSE_KEY").item(0).getChildNodes().item(0).getNodeValue());
        Info.setExpDate(infoNode.getElementsByTagName("EXPIRY_DATE").item(0).getChildNodes().item(0).getNodeValue());
        Info.setIp(infoNode.getElementsByTagName("HOST_IP").item(0).getChildNodes().item(0).getNodeValue());
        Info.setComName(infoNode.getElementsByTagName("COMPANY_NAME").item(0).getChildNodes().item(0).getNodeValue());
        Info.setVersion(infoNode.getElementsByTagName("VERSION").item(0).getChildNodes().item(0).getNodeValue());
        log.info("License Key: " + Info.getKey());
        log.info("Expiry Date: " + Info.getExpDate());
        log.info("Host IP    : " + Info.getIp());
        log.info("Company    : " + Info.getComName());
        log.info("Version    : " + Info.getVersion());
  
        this.readFlag = true;
      } catch (Exception e) {
        log.error("Error in parsing License File.", e);
      }
    }
  }

  public boolean validateLicence() {
    if (this.readFlag) {
      return(this.isValidLicense);
    }

    getXMLElements();
    boolean flag = false;
    synchronized(lock) {
      if (validateIP()) {
        String s = new String();
        for (Enumeration e = Modules.elements(); e.hasMoreElements(); ) {
          ModuleLicenceInfo ml = ((ModuleLicenceInfo)e.nextElement());
          s += ml.getName();
          s += ml.getType();
          s += ml.getNo();
        }
        s += Info.getIp();
        s += Info.getExpDate();
        s += Info.getVersion();
        try {
          if (TextUtility.encodeObject(md5util.getDigest(s)).equals(Info.getKey().trim().toString())) {
            flag = true;
          }
        } catch (Exception e) {
          log.error(Priority.INFO, e);
        }
      }
/*
      if (!flag) {
        for (Enumeration e = Modules.elements(); e.hasMoreElements(); ) {
          ModuleLicenceInfo ml = ( (ModuleLicenceInfo) e.nextElement());
          ml.setNo(-1);
        }
      }
*/
      this.isValidLicense = flag;
    }
    return flag;
  }

  private boolean withinSubnet(String hostIP) {
    String[] keyArry = null;
    String[] hostArry = null;
    boolean flag = true;

    keyArry = com.dcivision.framework.TextUtility.splitString(Info.getIp(), ".");
    hostArry = com.dcivision.framework.TextUtility.splitString(hostIP, ".");

    for (int i = 0; i < 4; i++) {
      if (! (keyArry[i].equals(hostArry[i]) || keyArry[i].equals("*"))) {
        flag = false;
        break;
      }
    }

    return flag;
  }

  private boolean validateIP() {
    getXMLElements();
    boolean flag = false;

    try {
      InetAddress[] addresses;
      addresses = InetAddress.getAllByName(InetAddress.getLocalHost().
                                           getHostName());
      if (addresses.length == 1 && "127.0.0.1".equals(addresses[0].getHostAddress())) {
        flag = true;
      } else {
        for (int i = 0; i < addresses.length; i++) {
          if (withinSubnet(addresses[i].getHostAddress())) {
            return (true);
          }
        }
      }
    } catch (UnknownHostException e) {
      log.error("Error When Validating Host", e);
    }
    return flag;
  }

  public LicenceInfo getLicenceInfo() {
    return(this.Info);
  }

  public void reload() {
    this.readFlag = false;
    this.isValidLicense = false;
    this.getXMLElements();
  }

  public static void main(String[] argv) throws Exception {
    SiteValidator s = new SiteValidator("D:/CVSHome/EIP/Source/web/WEB-INF/eip-license.xml");
    System.out.println(s.validateLicence());
  }

}